﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Web.Mvc.Fakes;
using IdleTest.MSTest;
using IdleTest.EFAndMVCDemo.MvcUI;
using System.Web;
using System.Web.Fakes;
using Microsoft.QualityTools.Testing.Fakes;
using System.Security.Fakes;
using System.Security.Principal.Fakes;
using IdleTest.EFAndMVCDemo.IServices.Fakes;
using IdleTest.EFAndMVCDemo.MvcUI.Fakes;
using IdleTest.EFAndMVCDemo.IServices;
using IdleTest.EFAndMVCDemo.Models;
using System.Web.Mvc;

namespace IdleTest.EFAndMVCDemo.MvcUITest
{
    [TestClass]
    public class AdultRoleAttributeTest
    {
        [TestMethod]
        public void FilterTest_用户未登陆跳转到登陆页面()
        {
            AdultRoleAttribute attr = new AdultRoleAttribute();
            StubActionExecutingContext context = new StubActionExecutingContext();

            //用户名为空断言应跳转到登陆页面
            context.HttpContextGet = () => StubHttpContext(string.Empty, true);
            context.Result = new StubActionResult();
            attr.OnActionExecuting(context);
            ControllerAssert.AssertRedirectResult(context.Result, UITestConfig.LoginUrl);

            //用户名不为空，但该用户未验证，断言应跳转到登陆页面
            context.HttpContextGet = () => StubHttpContext("zhangsan", false);
            context.Result = new StubActionResult();
            attr.OnActionExecuting(context);
            ControllerAssert.AssertRedirectResult(context.Result, UITestConfig.LoginUrl);
        }

        [TestMethod]
        public void FilterTest_用户已登陆但该用户已被删除跳转到登陆页面()
        {
            AdultRoleAttribute attr = new AdultRoleAttribute();
            StubActionExecutingContext context = new StubActionExecutingContext();

            //用户名不为空，该用户已验证，但是获取不到用户信息，仍不能访问
            context.HttpContextGet = () => StubHttpContext("zhangsan", true);
            context.Result = new StubActionResult();
            using (ShimsContext.Create())
            {
                ShimGetUserModel(null);
                attr.OnActionExecuting(context);
                ControllerAssert.AssertRedirectResult(context.Result, UITestConfig.LoginUrl);
            }
        }

        [TestMethod]
        public void FilterTest_未成年不能进入()
        {
            AdultRoleAttribute attr = new AdultRoleAttribute();
            StubActionExecutingContext context = new StubActionExecutingContext();
            AssertCommon.ResetAssertInsance(new ControllerAssertInstance());

            using (ShimsContext.Create())
            {
                //用户已验证，但年龄小于18，则断言返回相应的提示页面或内容                
                AssertCommon.AreEqual(attr.GetNotAdultView(),
                    GetFilterContextByAge(new StubActionExecutingContext(), 17).Result);
            }
        }

        [TestMethod]
        public void FilterTest_年龄大于或等于18可访问()
        {
            ValidAgeTest(18);
            ValidAgeTest(38);
        }

        public void ValidAgeTest(int age)
        {
            AdultRoleAttribute attr = new AdultRoleAttribute();
            StubActionExecutingContext context = new StubActionExecutingContext();

            using (ShimsContext.Create())
            {
                //用户已验证年龄大于等于18，断言进入Filter前后的Result应未变
                string viewName = "view";
                string masterName = "master";
                var expectedView = new StubViewResult();
                expectedView.ViewName = viewName;
                expectedView.MasterName = masterName;
                context.Result = expectedView;
                var actualView = GetFilterContextByAge(context, age).Result as ViewResult;
                AssertCommon.AreEqual(viewName, actualView.ViewName);
                AssertCommon.AreEqual(masterName, actualView.MasterName);
            }
        }

        public ActionExecutingContext GetFilterContextByAge(StubActionExecutingContext context, int age)
        {
            AdultRoleAttribute attr = new AdultRoleAttribute();

            ShimGetUserModel(new UserModel { Age = age });
            context.HttpContextGet = () => StubHttpContext("zhangsan", true);
            attr.OnActionExecuting(context);
            return context;
        }

        public void ShimGetUserModel(UserModel model)
        {
            ShimIocContainer.InstanceOf1<IUserService>(() => 
            {
                var userService = new StubIUserService();
                userService.GetModelString = p => model;
                return userService;
            });
        }

        public HttpContextBase StubHttpContext(string userName, bool isAuthenticated)
        {
            var context = new StubHttpContextBase();
            context.UserGet = () => 
            {
                var principal = new StubIPrincipal();
                principal.IdentityGet = () => 
                {
                    var id = new StubIIdentity();
                    id.IsAuthenticatedGet = () => isAuthenticated;
                    id.NameGet = () => userName;
                    return id;
                };

                return principal;
            };

            return context;
        }
    }
}
